'''
任务相关的API路由
'''
from flask import Blueprint, request, jsonify, g, current_app, Response, stream_with_context
from psycopg2.extras import RealDictCursor
import json
import time
from datetime import datetime
from utils.helpers import format_tasks_tree, check_task_dependencies, update_task_progress
from services.auth_service import verify_tenant_permission, auth_required
from services.project_service import get_project_by_id
import logging

# 创建蓝图
task_bp = Blueprint('task', __name__, url_prefix='/api')

# 5. 获取主任务详情
@task_bp.route('/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('SELECT * FROM main_tasks WHERE id = %s', (task_id,))
    task = cursor.fetchone()
    
    if not task:
        return jsonify({
            'status': 'error',
            'message': '任务不存在'
        }), 404
    
    # 获取最新的任务拆分版本
    cursor.execute('''
    SELECT * FROM task_breakdown_versions 
    WHERE main_task_id = %s AND status = 'active'
    ORDER BY version_number DESC LIMIT 1
    ''', (task_id,))
    breakdown_version = cursor.fetchone()
    
    task['breakdown_version'] = breakdown_version
    
    # 如果有任务拆分版本，获取子任务
    if breakdown_version:
        cursor.execute('''
        SELECT * FROM sub_tasks 
        WHERE breakdown_version_id = %s
        ORDER BY level, sequence
        ''', (breakdown_version['id'],))
        subtasks = cursor.fetchall()
        
        # 格式化为树形结构
        task['subtasks'] = format_tasks_tree(subtasks)
    else:
        task['subtasks'] = []
    
    return jsonify({
        'status': 'success',
        'data': task
    })

# 6. 手动拆分任务
@task_bp.route('/tasks/<int:task_id>/manual-breakdown', methods=['POST'])
@auth_required
def manual_breakdown(task_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 获取任务信息
    cursor.execute('SELECT * FROM main_tasks WHERE id = %s', (task_id,))
    task = cursor.fetchone()
    
    if not task:
        return jsonify({
            'status': 'error',
            'message': '任务不存在'
        }), 404
    
    # 从请求中获取子任务结构
    data = request.json
    if not data or 'tasks' not in data:
        return jsonify({
            'status': 'error',
            'message': '请提供任务拆分结构'
        }), 400
    
    # 获取当前版本号
    cursor.execute('''
    SELECT MAX(version_number) as current_version
    FROM task_breakdown_versions
    WHERE main_task_id = %s
    ''', (task_id,))
    
    version_result = cursor.fetchone()
    current_version = version_result['current_version'] if version_result['current_version'] else 0
    breakdown_version = current_version + 1
    
    # 获取用户名
    username = data.get('username', 'admin')
    
    # 将该任务所有现有拆分版本设置为非活跃状态
    cursor.execute('''
    UPDATE task_breakdown_versions
    SET status = 'archived'
    WHERE main_task_id = %s
    ''', (task_id,))
    
    # 创建新的拆分版本
    cursor.execute('''
    INSERT INTO task_breakdown_versions 
    (main_task_id, version_number, created_by, created_at, status)
    VALUES (%s, %s, %s, NOW(), 'active')
    RETURNING id
    ''', (
        task_id, 
        breakdown_version,
        username
    ))
    
    breakdown_id = cursor.fetchone()['id']
    
    # 保存子任务结构
    from services.ai_service import save_tasks_recursive
    from config.config import TASK_BREAKDOWN_CONFIG
    
    total_subtasks = save_tasks_recursive(
        data['tasks'],
        breakdown_id, 
        parent_task_id=None, 
        level=1, 
        conn=conn, 
        cursor=cursor, 
        task_breakdown_config=TASK_BREAKDOWN_CONFIG
    )
    
    # 更新任务拆分版本中的子任务计数
    cursor.execute('''
    UPDATE task_breakdown_versions
    SET total_subtasks = %s, completed_subtasks = 0
    WHERE id = %s
    ''', (total_subtasks, breakdown_id))
    
    # 更新主任务状态
    cursor.execute('''
    UPDATE main_tasks SET status = 'in_progress', updated_at = NOW()
    WHERE id = %s
    ''', (task_id,))
    
    conn.commit()
    
    return jsonify({
        'status': 'success',
        'data': {
            'breakdown_id': breakdown_id,
            'breakdown_version': breakdown_version,
            'total_subtasks': total_subtasks
        }
    })

# 获取任务拆分版本列表
@task_bp.route('/tasks/<int:task_id>/breakdown-versions', methods=['GET'])
def get_task_breakdown_versions(task_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('''
    SELECT * FROM task_breakdown_versions
    WHERE main_task_id = %s
    ORDER BY version_number DESC
    ''', (task_id,))
    
    versions = cursor.fetchall()
    
    return jsonify({
        'status': 'success',
        'data': versions
    })

# 获取特定拆分版本详情
@task_bp.route('/breakdown-versions/<int:version_id>', methods=['GET'])
def get_breakdown_version(version_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('SELECT * FROM task_breakdown_versions WHERE id = %s', (version_id,))
    version = cursor.fetchone()
    
    if not version:
        return jsonify({
            'status': 'error',
            'message': '拆分版本不存在'
        }), 404
    
    cursor.execute('''
    SELECT * FROM sub_tasks
    WHERE breakdown_version_id = %s
    ORDER BY level, sequence
    ''', (version_id,))
    
    subtasks = cursor.fetchall()
    
    version['subtasks'] = format_tasks_tree(subtasks)
    
    return jsonify({
        'status': 'success',
        'data': version
    })

# 更新特定子任务
@task_bp.route('/subtasks/<int:subtask_id>', methods=['PUT'])
@auth_required
def update_subtask(subtask_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('SELECT * FROM sub_tasks WHERE id = %s', (subtask_id,))
    subtask = cursor.fetchone()
    
    if not subtask:
        return jsonify({
            'status': 'error',
            'message': '子任务不存在'
        }), 404
    
    data = request.json
    if not data:
        return jsonify({
            'status': 'error',
            'message': '请提供更新数据'
        }), 400
    
    # 可更新的字段
    allowed_fields = ['title', 'description', 'status', 'is_atomic', 'estimated_hours']
    update_data = {k: v for k, v in data.items() if k in allowed_fields}
    
    if not update_data:
        return jsonify({
            'status': 'error',
            'message': '没有有效的更新字段'
        }), 400
    
    # 构建SQL更新语句
    update_fields = ', '.join([f"{k} = %s" for k in update_data.keys()])
    update_values = list(update_data.values())
    
    cursor.execute(f'''
    UPDATE sub_tasks
    SET {update_fields}, updated_at = NOW()
    WHERE id = %s
    RETURNING *
    ''', update_values + [subtask_id])
    
    updated_subtask = cursor.fetchone()
    conn.commit()
    
    return jsonify({
        'status': 'success',
        'data': updated_subtask
    })

# 执行任务
@task_bp.route('/subtasks/<int:subtask_id>/execute', methods=['POST'])
@auth_required
def execute_subtask(subtask_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('SELECT * FROM sub_tasks WHERE id = %s', (subtask_id,))
    subtask = cursor.fetchone()
    
    if not subtask:
        return jsonify({
            'status': 'error',
            'message': '子任务不存在'
        }), 404
    
    data = request.json or {}
    executor = data.get('executor', 'manual')
    execution_result = data.get('result', '')
    
    # 更新子任务状态
    cursor.execute('''
    UPDATE sub_tasks
    SET status = 'completed', execution_result = %s, executed_by = %s, executed_at = NOW(), updated_at = NOW()
    WHERE id = %s
    RETURNING *
    ''', (execution_result, executor, subtask_id))
    
    updated_subtask = cursor.fetchone()
    
    # 更新父任务和拆分版本的进度
    update_task_progress(conn, cursor, subtask['breakdown_version_id'])
    
    conn.commit()
    
    return jsonify({
        'status': 'success',
        'data': updated_subtask
    })

# 更新任务拆分版本状态
@task_bp.route('/breakdown-versions/<int:version_id>/status', methods=['PUT'])
@auth_required
def update_breakdown_version_status(version_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('SELECT * FROM task_breakdown_versions WHERE id = %s', (version_id,))
    version = cursor.fetchone()
    
    if not version:
        return jsonify({
            'status': 'error',
            'message': '拆分版本不存在'
        }), 404
    
    data = request.json
    if not data or 'status' not in data:
        return jsonify({
            'status': 'error',
            'message': '请提供状态信息'
        }), 400
    
    # 如果要激活此版本，首先将同一任务的其他版本设置为非激活
    if data['status'] == 'active':
        cursor.execute('''
        UPDATE task_breakdown_versions
        SET status = 'archived'
        WHERE main_task_id = %s AND id != %s
        ''', (version['main_task_id'], version_id))
    
    # 更新当前版本状态
    try:
        cursor.execute('''
        UPDATE task_breakdown_versions
        SET status = %s
        WHERE id = %s
        RETURNING *
        ''', (data['status'], version_id))
        
        updated_version = cursor.fetchone()
        conn.commit()
        
        return jsonify({
            'status': 'success',
            'data': updated_version
        })
    except Exception as e:
        conn.rollback()
        return jsonify({
            'status': 'error',
            'message': f'更新版本状态失败: {str(e)}'
        }), 500

# 添加新的子任务
@task_bp.route('/breakdown-versions/<int:version_id>/subtasks', methods=['POST'])
@auth_required
def add_subtask(version_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 验证分解版本是否存在
    cursor.execute('SELECT * FROM task_breakdown_versions WHERE id = %s', (version_id,))
    version = cursor.fetchone()
    
    if not version:
        return jsonify({
            'status': 'error',
            'message': '拆分版本不存在'
        }), 404
    
    # 获取请求数据
    data = request.json
    if not data:
        return jsonify({
            'status': 'error',
            'message': '请提供子任务数据'
        }), 400
    
    # 必需字段验证
    required_fields = ['title']
    for field in required_fields:
        if field not in data:
            return jsonify({
                'status': 'error',
                'message': f'缺少必需字段：{field}'
            }), 400
    
    # 处理父任务ID
    parent_task_id = data.get('parent_task_id', None)
    if parent_task_id:
        # 验证父任务是否存在并属于该版本
        cursor.execute('''
        SELECT * FROM sub_tasks 
        WHERE id = %s AND breakdown_version_id = %s
        ''', (parent_task_id, version_id))
        parent_task = cursor.fetchone()
        
        if not parent_task:
            return jsonify({
                'status': 'error',
                'message': '父任务不存在或不属于该拆分版本'
            }), 404
        
        # 确定任务级别（父任务级别+1）
        level = parent_task['level'] + 1
    else:
        # 顶级任务，级别为1
        level = 1
    
    # 确定任务顺序（在同级和同父任务下的最后一个）
    cursor.execute('''
    SELECT MAX(sequence) as max_sequence 
    FROM sub_tasks 
    WHERE breakdown_version_id = %s AND parent_task_id IS NOT DISTINCT FROM %s AND level = %s
    ''', (version_id, parent_task_id, level))
    
    max_sequence = cursor.fetchone()['max_sequence'] or 0
    sequence = max_sequence + 1
    
    # 插入子任务
    cursor.execute('''
    INSERT INTO sub_tasks 
    (breakdown_version_id, parent_task_id, title, description, level, sequence, is_atomic, estimated_hours)
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
    RETURNING *
    ''', (
        version_id,
        parent_task_id,
        data['title'],
        data.get('description', ''),
        level,
        sequence,
        data.get('is_atomic', False),
        data.get('estimated_hours', 1.0)
    ))
    
    new_subtask = cursor.fetchone()
    
    # 更新任务拆分版本中的子任务计数
    cursor.execute('''
    UPDATE task_breakdown_versions
    SET total_subtasks = total_subtasks + 1
    WHERE id = %s
    ''', (version_id,))
    
    # 处理任务依赖关系（如果提供）
    if 'dependencies' in data and isinstance(data['dependencies'], list):
        from utils.helpers import add_task_dependency
        
        dependencies_added = []
        for dep_id in data['dependencies']:
            # 验证依赖任务是否存在并属于该版本
            cursor.execute('''
            SELECT * FROM sub_tasks 
            WHERE id = %s AND breakdown_version_id = %s
            ''', (dep_id, version_id))
            
            if cursor.fetchone():
                dependency = add_task_dependency(
                    new_subtask['id'], 
                    dep_id, 
                    data.get('dependency_type', 'finish_to_start'),
                    data.get('is_critical', False)
                )
                if dependency:
                    dependencies_added.append(dependency)
        
        new_subtask['dependencies'] = dependencies_added
    
    conn.commit()
    
    return jsonify({
        'status': 'success',
        'message': '子任务添加成功',
        'data': new_subtask
    })

# 获取子任务详情
@task_bp.route('/subtasks/<int:subtask_id>', methods=['GET'])
def get_subtask(subtask_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 查询子任务基本信息
    cursor.execute('''
    SELECT st.*, tbv.main_task_id 
    FROM sub_tasks st
    JOIN task_breakdown_versions tbv ON st.breakdown_version_id = tbv.id
    WHERE st.id = %s
    ''', (subtask_id,))
    
    subtask = cursor.fetchone()
    
    if not subtask:
        return jsonify({
            'status': 'error',
            'message': '子任务不存在'
        }), 404
    
    # 查询子任务的依赖关系
    cursor.execute('''
    SELECT td.*, st.title as dependency_title
    FROM task_dependencies td
    JOIN sub_tasks st ON td.dependency_task_id = st.id
    WHERE td.dependent_task_id = %s
    ''', (subtask_id,))
    
    dependencies = cursor.fetchall()
    
    # 查询该子任务的子任务
    cursor.execute('''
    SELECT * FROM sub_tasks
    WHERE parent_task_id = %s
    ORDER BY level, sequence
    ''', (subtask_id,))
    
    children = cursor.fetchall()
    
    # 整合数据
    result = subtask
    result['dependencies'] = dependencies
    result['children'] = children
    
    return jsonify({
        'status': 'success',
        'data': result
    })

# 删除子任务
@task_bp.route('/subtasks/<int:subtask_id>', methods=['DELETE'])
@auth_required
def delete_subtask(subtask_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 查询子任务是否存在
    cursor.execute('SELECT * FROM sub_tasks WHERE id = %s', (subtask_id,))
    subtask = cursor.fetchone()
    
    if not subtask:
        return jsonify({
            'status': 'error',
            'message': '子任务不存在'
        }), 404
    
    # 删除子任务及其所有子任务（递归删除）
    def delete_subtask_recursive(task_id):
        # 先递归删除所有子任务
        cursor.execute('SELECT id FROM sub_tasks WHERE parent_task_id = %s', (task_id,))
        children = cursor.fetchall()
        for child in children:
            delete_subtask_recursive(child['id'])
        
        # 删除与该任务相关的依赖关系
        cursor.execute('DELETE FROM task_dependencies WHERE dependent_task_id = %s OR dependency_task_id = %s', 
                      (task_id, task_id))
        
        # 删除任务本身
        cursor.execute('DELETE FROM sub_tasks WHERE id = %s', (task_id,))
    
    try:
        delete_subtask_recursive(subtask_id)
        
        # 更新任务拆分版本中的子任务计数
        cursor.execute('''
        UPDATE task_breakdown_versions
        SET total_subtasks = (
            SELECT COUNT(*) 
            FROM sub_tasks 
            WHERE breakdown_version_id = %s
        )
        WHERE id = %s
        ''', (subtask['breakdown_version_id'], subtask['breakdown_version_id']))
        
        conn.commit()
        
        return jsonify({
            'status': 'success',
            'message': '子任务及其所有子任务已成功删除'
        })
    except Exception as e:
        conn.rollback()
        return jsonify({
            'status': 'error',
            'message': f'删除子任务失败: {str(e)}'
        }), 500

# 获取原子任务列表
@task_bp.route('/tasks/atomic', methods=['GET'])
def get_atomic_tasks():
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('''
    SELECT 
        st.id, 
        st.title, 
        st.description, 
        st.status, 
        st.estimated_hours,
        st.is_atomic,
        st.created_at,
        st.updated_at,
        mt.id as main_task_id,
        mt.title as main_task_title,
        p.id as project_id,
        p.name as project_name
    FROM sub_tasks st
    JOIN task_breakdown_versions tbv ON st.breakdown_version_id = tbv.id
    JOIN main_tasks mt ON tbv.main_task_id = mt.id
    JOIN projects p ON mt.project_id = p.id
    WHERE st.is_atomic = TRUE AND tbv.status = 'active' AND st.status != 'completed'
    ORDER BY st.created_at DESC
    ''')
    
    tasks = cursor.fetchall()
    
    return jsonify({
        'status': 'success',
        'data': tasks
    })

# 获取原子任务详情
@task_bp.route('/tasks/atomic/<int:task_id>', methods=['GET'])
def get_atomic_task_detail(task_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 获取原子任务详情
    cursor.execute('''
    SELECT 
        st.*, 
        mt.id as main_task_id,
        mt.title as main_task_title,
        p.id as project_id,
        p.name as project_name
    FROM sub_tasks st
    JOIN task_breakdown_versions tbv ON st.breakdown_version_id = tbv.id
    JOIN main_tasks mt ON tbv.main_task_id = mt.id
    JOIN projects p ON mt.project_id = p.id
    WHERE st.id = %s AND st.is_atomic = TRUE
    ''', (task_id,))
    
    task = cursor.fetchone()
    
    if not task:
        return jsonify({
            'status': 'error',
            'message': '原子任务不存在'
        }), 404
    
    # 获取任务执行历史
    cursor.execute('''
    SELECT * FROM task_executions
    WHERE sub_task_id = %s
    ORDER BY started_at DESC
    ''', (task_id,))
    
    executions = cursor.fetchall()
    
    # 获取任务依赖关系
    cursor.execute('''
    SELECT td.*, st.title as dependency_title
    FROM task_dependencies td
    JOIN sub_tasks st ON td.dependency_task_id = st.id
    WHERE td.dependent_task_id = %s
    ''', (task_id,))
    
    dependencies = cursor.fetchall()
    
    # 构建响应
    result = {
        'task': task,
        'executions': executions,
        'dependencies': dependencies
    }
    
    return jsonify({
        'status': 'success',
        'data': result
    })

# 添加新的子任务（依赖拆分版本）
@task_bp.route('/subtasks', methods=['POST'])
@auth_required
def add_subtask_direct():
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 获取请求数据
    data = request.json
    if not data:
        return jsonify({
            'status': 'error',
            'message': '请提供子任务数据'
        }), 400
    
    # 必需字段验证
    required_fields = ['title', 'breakdown_version_id']
    for field in required_fields:
        if field not in data:
            return jsonify({
                'status': 'error',
                'message': f'缺少必需字段：{field}'
            }), 400
    
    # 验证拆分版本是否存在
    breakdown_version_id = data['breakdown_version_id']
    cursor.execute('SELECT * FROM task_breakdown_versions WHERE id = %s', (breakdown_version_id,))
    version = cursor.fetchone()
    
    if not version:
        return jsonify({
            'status': 'error',
            'message': '拆分版本不存在'
        }), 404
    
    # 处理父任务ID
    parent_task_id = data.get('parent_task_id', None)
    if parent_task_id:
        # 验证父任务是否存在并属于该版本
        cursor.execute('''
        SELECT * FROM sub_tasks 
        WHERE id = %s AND breakdown_version_id = %s
        ''', (parent_task_id, breakdown_version_id))
        parent_task = cursor.fetchone()
        
        if not parent_task:
            return jsonify({
                'status': 'error',
                'message': '父任务不存在或不属于该拆分版本'
            }), 404
        
        # 确定任务级别（父任务级别+1）
        level = parent_task['level'] + 1
    else:
        # 顶级任务，级别为1
        level = 1
    
    # 确定任务顺序（在同级和同父任务下的最后一个）
    cursor.execute('''
    SELECT MAX(sequence) as max_sequence 
    FROM sub_tasks 
    WHERE breakdown_version_id = %s AND parent_task_id IS NOT DISTINCT FROM %s AND level = %s
    ''', (breakdown_version_id, parent_task_id, level))
    
    max_sequence = cursor.fetchone()['max_sequence'] or 0
    sequence = max_sequence + 1
    
    # 插入子任务
    cursor.execute('''
    INSERT INTO sub_tasks 
    (breakdown_version_id, parent_task_id, title, description, level, sequence, is_atomic, estimated_hours)
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
    RETURNING *
    ''', (
        breakdown_version_id,
        parent_task_id,
        data['title'],
        data.get('description', ''),
        level,
        sequence,
        data.get('is_atomic', False),
        data.get('estimated_hours', 1.0)
    ))
    
    new_subtask = cursor.fetchone()
    
    # 更新任务拆分版本中的子任务计数
    cursor.execute('''
    UPDATE task_breakdown_versions
    SET total_subtasks = total_subtasks + 1
    WHERE id = %s
    ''', (breakdown_version_id,))
    
    # 处理任务依赖关系（如果提供）
    if 'dependencies' in data and isinstance(data['dependencies'], list):
        from utils.helpers import add_task_dependency
        
        dependencies_added = []
        for dep_id in data['dependencies']:
            # 验证依赖任务是否存在并属于该版本
            cursor.execute('''
            SELECT * FROM sub_tasks 
            WHERE id = %s AND breakdown_version_id = %s
            ''', (dep_id, breakdown_version_id))
            
            if cursor.fetchone():
                dependency = add_task_dependency(
                    new_subtask['id'], 
                    dep_id, 
                    data.get('dependency_type', 'finish_to_start'),
                    data.get('is_critical', False)
                )
                if dependency:
                    dependencies_added.append(dependency)
        
        new_subtask['dependencies'] = dependencies_added
    
    conn.commit()
    
    return jsonify({
        'status': 'success',
        'message': '子任务添加成功',
        'data': new_subtask
    })

# 获取任务详情(包括项目信息)
@task_bp.route('/tasks/<int:task_id>/detail', methods=['GET'])
def get_task_detail(task_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 获取任务详情并关联项目信息
    cursor.execute('''
    SELECT t.*, p.id as project_id, p.name as project_name, 
           p.git_repository_url, p.project_folder_path 
    FROM main_tasks t
    LEFT JOIN projects p ON t.project_id = p.id
    WHERE t.id = %s
    ''', (task_id,))
    
    task = cursor.fetchone()
    
    if not task:
        return jsonify({
            'status': 'error',
            'message': '任务不存在'
        }), 404
    
    # 构建项目信息
    if task['project_id']:
        task['project'] = {
            'id': task['project_id'],
            'name': task['project_name'],
            'git_repository_url': task['git_repository_url'],
            'project_folder_path': task['project_folder_path']
        }
    
    # 移除冗余字段
    task.pop('project_id', None)
    task.pop('project_name', None)
    task.pop('git_repository_url', None)
    task.pop('project_folder_path', None)
    
    # 获取最新的任务拆分版本
    cursor.execute('''
    SELECT * FROM task_breakdown_versions 
    WHERE main_task_id = %s AND status = 'active'
    ORDER BY version_number DESC LIMIT 1
    ''', (task_id,))
    breakdown_version = cursor.fetchone()
    
    task['breakdown_version'] = breakdown_version
    
    # 如果有任务拆分版本，获取子任务
    if breakdown_version:
        cursor.execute('''
        SELECT * FROM sub_tasks 
        WHERE breakdown_version_id = %s
        ORDER BY level, sequence
        ''', (breakdown_version['id'],))
        subtasks = cursor.fetchall()
        
        # 格式化为树形结构
        task['subtasks'] = format_tasks_tree(subtasks)
    else:
        task['subtasks'] = []
    
    return jsonify({
        'status': 'success',
        'data': task
    })

# 获取子任务的Git操作相关信息
@task_bp.route('/subtasks/<int:subtask_id>/git-info', methods=['GET'])
def get_subtask_git_info(subtask_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    try:
        # 1. 获取子任务信息
        cursor.execute('''
        SELECT st.*, tbv.main_task_id, tbv.id as breakdown_version_id 
        FROM sub_tasks st
        JOIN task_breakdown_versions tbv ON st.breakdown_version_id = tbv.id
        WHERE st.id = %s
        ''', (subtask_id,))
        
        subtask = cursor.fetchone()
        
        if not subtask:
            return jsonify({
                'status': 'error',
                'message': '子任务不存在'
            }), 404
        
        # 2. 获取主任务信息
        cursor.execute('''
        SELECT mt.*, p.id as project_id, p.name as project_name, 
               p.git_repository_url, p.git_username, p.git_password, p.git_branch,
               p.project_folder_path
        FROM main_tasks mt
        JOIN projects p ON mt.project_id = p.id
        WHERE mt.id = %s
        ''', (subtask['main_task_id'],))
        
        main_task = cursor.fetchone()
        
        if not main_task:
            return jsonify({
                'status': 'error',
                'message': '主任务不存在'
            }), 404
        
        # 3. 构建结果对象
        result = {
            'subtask': {
                'id': subtask.get('id'),
                'title': subtask.get('title', '未命名子任务'),
                'description': subtask.get('description', ''),
                'status': subtask.get('status', 'unknown'),
                'level': subtask.get('level', 0),
                'sequence': subtask.get('sequence', 0),
                'is_atomic': subtask.get('is_atomic', False),
                'breakdown_version_id': subtask.get('breakdown_version_id')
            },
            'main_task': {
                'id': main_task.get('id'),
                'name': main_task.get('name', '未命名任务'),
                'status': main_task.get('status', 'unknown'),
                'description': main_task.get('description', ''),
                'repository_path': main_task.get('repository_path', '')
            },
            'project': {
                'id': main_task.get('project_id'),
                'name': main_task.get('project_name', '未命名项目'),
                'git_repository_url': main_task.get('git_repository_url', ''),
                'git_username': main_task.get('git_username', ''),
                'git_branch': main_task.get('git_branch', 'main'),
                'git_password': '******',  # 出于安全考虑不返回真实密码
                'project_folder_path': main_task.get('project_folder_path', '')
            }
        }
        
        return jsonify({
            'status': 'success',
            'data': result
        })
    except Exception as e:
        # 记录详细错误
        current_app.logger.error(f"获取子任务Git信息失败: {str(e)}", exc_info=True)
        return jsonify({
            'status': 'error',
            'message': '服务器发生错误',
            'error': str(e)
        }), 500 

# 获取任务执行历史
@task_bp.route('/tasks/<int:task_id>/executions', methods=['GET'])
@auth_required
def get_task_executions(task_id):
    """获取任务的执行历史记录"""
    try:
        conn = g.db
        cursor = conn.cursor(cursor_factory=RealDictCursor)
        
        # 首先检查任务是否存在
        cursor.execute('''
            SELECT EXISTS(
                SELECT 1 
                FROM atomic_tasks 
                WHERE id = %s
            )
        ''', (task_id,))
        
        task_exists = cursor.fetchone()['exists']
        
        if not task_exists:
            return jsonify({
                'status': 'error',
                'message': '任务不存在'
            }), 404
        
        # 获取任务执行历史
        cursor.execute('''
            SELECT 
                te.id,
                te.task_id,
                te.action,
                te.description,
                te.status,
                te.result,
                te.executed_by,
                te.created_at as execution_time,
                te.review_status,
                te.review_comment,
                te.reviewed_by,
                te.reviewed_at
            FROM task_executions te
            WHERE te.task_id = %s
            ORDER BY te.created_at DESC
        ''', (task_id,))
        
        executions = cursor.fetchall()
        
        # 处理结果字段
        for execution in executions:
            if execution['result']:
                try:
                    execution['result'] = json.loads(execution['result'])
                except:
                    # 如果JSON解析失败，保持原始字符串
                    pass
        
        return jsonify({
            'success': True,
            'executions': executions
        })
        
    except Exception as e:
        current_app.logger.error(f"获取任务执行历史失败: {str(e)}")
        return jsonify({
            'success': False,
            'message': f"获取任务执行历史失败: {str(e)}"
        }), 500 

# 获取拆分版本下的所有子任务
@task_bp.route('/breakdown-versions/<int:version_id>/subtasks', methods=['GET'])
def get_subtasks_by_version(version_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 验证分解版本是否存在
    cursor.execute('SELECT * FROM task_breakdown_versions WHERE id = %s', (version_id,))
    version = cursor.fetchone()
    
    if not version:
        return jsonify({
            'status': 'error',
            'message': '拆分版本不存在'
        }), 404
    
    # 获取该版本下的所有子任务
    cursor.execute('''
    SELECT * FROM sub_tasks
    WHERE breakdown_version_id = %s
    ORDER BY level, sequence
    ''', (version_id,))
    
    subtasks = cursor.fetchall()
    
    # 格式化为树形结构
    formatted_subtasks = format_tasks_tree(subtasks)
    
    return jsonify({
        'status': 'success',
        'data': formatted_subtasks
    })

# 批量更新子任务
@task_bp.route('/subtasks/batch-update', methods=['POST'])
@auth_required
def batch_update_subtasks():
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    data = request.json
    if not data or 'subtasks' not in data or not isinstance(data['subtasks'], list):
        return jsonify({
            'status': 'error',
            'message': '请提供有效的子任务数据'
        }), 400
    
    updated_subtasks = []
    try:
        for subtask in data['subtasks']:
            if 'id' not in subtask:
                continue
                
            # 生成动态SQL更新
            update_fields = []
            params = []
            
            if 'title' in subtask:
                update_fields.append('title = %s')
                params.append(subtask['title'])
                
            if 'description' in subtask:
                update_fields.append('description = %s')
                params.append(subtask['description'])
                
            if 'status' in subtask:
                update_fields.append('status = %s')
                params.append(subtask['status'])
                
            if 'is_atomic' in subtask:
                update_fields.append('is_atomic = %s')
                params.append(subtask['is_atomic'])
                
            if 'estimated_hours' in subtask:
                update_fields.append('estimated_hours = %s')
                params.append(subtask['estimated_hours'])
                
            if not update_fields:  # 如果没有需要更新的字段，跳过
                continue
                
            # 添加最后一个参数：子任务ID
            params.append(subtask['id'])
            
            # 构建并执行更新SQL
            update_sql = f'''
            UPDATE sub_tasks 
            SET {', '.join(update_fields)}, updated_at = NOW()
            WHERE id = %s
            RETURNING *
            '''
            
            cursor.execute(update_sql, params)
            updated = cursor.fetchone()
            
            if updated:
                updated_subtasks.append(updated)
        
        conn.commit()
        
        return jsonify({
            'status': 'success',
            'message': f'成功更新 {len(updated_subtasks)} 个子任务',
            'data': updated_subtasks
        })
        
    except Exception as e:
        conn.rollback()
        current_app.logger.error(f"批量更新子任务失败: {str(e)}", exc_info=True)
        return jsonify({
            'status': 'error',
            'message': '批量更新失败',
            'error': str(e)
        }), 500 

# 激活任务拆分版本
@task_bp.route('/breakdown-versions/<int:version_id>/activate', methods=['PUT'])
@auth_required
def activate_breakdown_version(version_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    cursor.execute('SELECT * FROM task_breakdown_versions WHERE id = %s', (version_id,))
    version = cursor.fetchone()
    
    if not version:
        return jsonify({
            'status': 'error',
            'message': '拆分版本不存在'
        }), 404
    
    try:
        # 首先将同一任务的所有版本设置为非激活
        cursor.execute('''
        UPDATE task_breakdown_versions
        SET status = 'archived'
        WHERE main_task_id = %s
        ''', (version['main_task_id'],))
        
        # 然后激活当前版本
        cursor.execute('''
        UPDATE task_breakdown_versions
        SET status = 'active'
        WHERE id = %s
        RETURNING *
        ''', (version_id,))
        
        activated_version = cursor.fetchone()
        conn.commit()
        
        return jsonify({
            'status': 'success',
            'message': '版本激活成功',
            'data': activated_version
        })
    except Exception as e:
        conn.rollback()
        return jsonify({
            'status': 'error',
            'message': f'激活版本失败: {str(e)}'
        }), 500 

# 删除任务拆分版本
@task_bp.route('/breakdown-versions/<int:version_id>', methods=['DELETE'])
@auth_required
def delete_breakdown_version(version_id):
    conn = g.db
    cursor = conn.cursor(cursor_factory=RealDictCursor)
    
    # 设置为自动提交模式为False - 在开始任何查询前设置
    conn.autocommit = False
    
    try:
        # 验证拆分版本是否存在
        cursor.execute('SELECT * FROM task_breakdown_versions WHERE id = %s', (version_id,))
        version = cursor.fetchone()
        
        if not version:
            conn.rollback()  # 回滚任何操作
            return jsonify({
                'status': 'error',
                'message': '拆分版本不存在'
            }), 404
        
        # 检查是否为活跃版本，活跃版本不允许删除
        if version['status'] == 'active':
            conn.rollback()  # 回滚任何操作
            return jsonify({
                'status': 'error',
                'message': '活跃版本不允许删除，请先激活其他版本'
            }), 400
        
        # 在进入事务之前先记录日志，便于调试
        current_app.logger.info(f"开始删除拆分版本 ID:{version_id}, 版本号:{version.get('version_number')}")
        
        # 获取此版本下的所有子任务ID
        cursor.execute('SELECT id FROM sub_tasks WHERE breakdown_version_id = %s', (version_id,))
        subtask_ids = [row['id'] for row in cursor.fetchall()]
        
        current_app.logger.info(f"找到 {len(subtask_ids)} 个关联子任务")
        
        # 删除子任务相关的依赖关系
        if subtask_ids:
            # 改为参数化查询，避免SQL注入和长查询问题
            # 批量处理，每500个ID一批
            batch_size = 500
            for i in range(0, len(subtask_ids), batch_size):
                batch = subtask_ids[i:i+batch_size]
                # 删除依赖关系 - 作为被依赖项
                try:
                    cursor.execute(
                        'DELETE FROM task_dependencies WHERE dependency_task_id = ANY(%s)',
                        (batch,)
                    )
                    current_app.logger.info(f"成功删除依赖关系 - 被依赖项 (批次 {i//batch_size+1})")
                except Exception as e:
                    current_app.logger.error(f"删除依赖关系(被依赖项)失败: {str(e)}")
                    raise
                
                # 删除依赖关系 - 作为依赖项
                try:
                    cursor.execute(
                        'DELETE FROM task_dependencies WHERE dependent_task_id = ANY(%s)',
                        (batch,)
                    )
                    current_app.logger.info(f"成功删除依赖关系 - 依赖项 (批次 {i//batch_size+1})")
                except Exception as e:
                    current_app.logger.error(f"删除依赖关系(依赖项)失败: {str(e)}")
                    raise
        
        # 删除所有子任务
        try:
            cursor.execute('DELETE FROM sub_tasks WHERE breakdown_version_id = %s', (version_id,))
            current_app.logger.info(f"成功删除所有子任务")
        except Exception as e:
            current_app.logger.error(f"删除子任务失败: {str(e)}")
            raise
        
        # 删除拆分版本
        try:
            cursor.execute('DELETE FROM task_breakdown_versions WHERE id = %s RETURNING main_task_id', (version_id,))
            result = cursor.fetchone()
            if not result:
                current_app.logger.error("删除版本后无法获取main_task_id")
                raise Exception("删除拆分版本后无法获取main_task_id")
            
            main_task_id = result['main_task_id']
            current_app.logger.info(f"成功删除拆分版本, main_task_id: {main_task_id}")
        except Exception as e:
            current_app.logger.error(f"删除拆分版本失败: {str(e)}")
            raise
        
        # 提交事务
        conn.commit()
        current_app.logger.info("事务提交成功")
        
        return jsonify({
            'status': 'success',
            'message': '拆分版本删除成功',
            'data': {
                'main_task_id': main_task_id
            }
        })
    except Exception as e:
        # 回滚事务
        try:
            conn.rollback()
            current_app.logger.info("事务回滚成功")
        except Exception as rollback_error:
            current_app.logger.error(f"事务回滚失败: {str(rollback_error)}")
        
        error_msg = str(e)
        current_app.logger.error(f"删除拆分版本失败: {error_msg}", exc_info=True)
        return jsonify({
            'status': 'error',
            'message': f'删除拆分版本失败: {error_msg}'
        }), 500
    finally:
        # 恢复自动提交模式
        try:
            conn.autocommit = True
            current_app.logger.info("已恢复autocommit模式")
        except Exception as ac_error:
            current_app.logger.error(f"恢复autocommit模式失败: {str(ac_error)}") 